package com.wispx.gateway.core.netty;

import com.wispx.gateway.config.config.Config;
import com.wispx.gateway.config.config.HttpClientConfig;
import com.wispx.gateway.core.container.Lifecycle;
import com.wispx.gateway.core.http.HttpClient;
import com.wispx.gateway.core.util.OSUtil;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.asynchttpclient.AsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * NettyHttpClient 客户端，将请求转发到下游服务
 */
@Slf4j
public class NettyHttpClient implements Lifecycle {

    private Config config;
    private EventLoopGroup eventLoopGroupWorker;
    private AsyncHttpClient asyncHttpClient;
    private AtomicBoolean start = new AtomicBoolean(false);

    public NettyHttpClient(Config config) {
        this.config = config;
    }

    @Override
    public void start() {
        if (config == null || !start.compareAndSet(false, true)) {
            return;
        }
        int workerNum = config.getHttpClient().getEventLoopGroupWorkerNum();
        eventLoopGroupWorker = OSUtil.supportEpoll() ?
                new EpollEventLoopGroup(workerNum, new DefaultThreadFactory("epoll-http-client-worker-nio")) :
                new NioEventLoopGroup(workerNum, new DefaultThreadFactory("default-http-client-worker-nio"));
        HttpClientConfig httpClient = config.getHttpClient();
        DefaultAsyncHttpClientConfig.Builder builder = new DefaultAsyncHttpClientConfig.Builder()
                .setConnectTimeout(httpClient.getHttpConnectTimeout()) // 连接超时时间
                .setRequestTimeout(httpClient.getHttpRequestTimeout()) // 请求超时时间
                .setMaxRedirects(httpClient.getHttpMaxRedirects()) // 最大重定向次数
                .setMaxConnections(httpClient.getHttpMaxConnections())// 最大连接数
                .setMaxConnectionsPerHost(httpClient.getHttpMaxConnectionsPerHost()) // 每个主机最大连接数
                .setMaxRequestRetry(httpClient.getHttpMaxRequestRetry()) // 最大重试次数
                .setPooledConnectionIdleTimeout(httpClient.getHttpPoolConnectionIdleTimeout()) // 连接池中线程最大存活时间
                .setAllocator(ByteBufAllocator.DEFAULT) // 分配器？
                .setEventLoopGroup(eventLoopGroupWorker) // 事件循环组？
                .setCompressionEnforced(true); // 强制压缩
        // 创建异步HTTP客户端
        this.asyncHttpClient = new DefaultAsyncHttpClient(builder.build());
        HttpClient.getInstance().initialized(asyncHttpClient);
        log.info("success init asyncHttpClient");
    }

    @Override
    public void shutdown() {
        if (!start.get()) {
            try {
                asyncHttpClient.close();
            } catch (IOException e) {
                log.warn("asyncHttpClient close err!!!");
            }
        }
    }

    @Override
    public boolean isStart() {
        return start.get();
    }
}
